Uploader=function(customOption){
		var self = this;
		let access_token=localStorage.getItem("access_token");
		let headers={"Authorization":access_token};
		var defaultOption={
				browse_button : 'pickfiles', //触发文件选择对话框的DOM元素，当点击该元素后便后弹出文件选择对话框。该值可以是DOM元素对象本身，也可以是该DOM元素的id
				runtimes:"html5",
				uploadfiles:"uploadfiles",//开始上传按钮id
				url : "/authenticated/upload",//服务器端接收和处理上传文件的脚本地址，可以是相对路径(相对于当前调用Plupload的文档)，也可以是绝对路径
				multi_selection:true,//是否可以在文件浏览对话框中选择多个文件，true为可以，false为不可以
				multiple_queues:false,//是否可以多次上传
				unique_names : true,//当值为true时会为每个上传的文件生成一个唯一的文件名，并作为额外的参数post到服务器端，参数明为name,值为生成的文件名。
				max_file_size : '10mb', //上传最大限制
		        chunk_size : '1mb', //分片上传文件时，每片文件被切割成的大小，为数字时单位为字节。也可以使用一个带单位的字符串，如"200kb"。当该值为0时表示不使用分片上传功能，这个值小于服务器最大上传限制的值即可。 
		        multipart:true,//为true时将以multipart/form-data的形式来上传文件，为false时则以二进制的格式来上传文件。html4上传方式不支持以二进制格式来上传文件，在flash上传方式中，二进制上传也有点问题。并且二进制格式上传还需要在服务器端做特殊的处理。一般我们用multipart/form-data的形式来上传文件就足够了。
		        file_data_name:'file',//指定文件上传时文件域的名称，默认为file
		        headers:headers,
				filters : {
					max_file_size : '10mb',
		            mime_types: [
		                {title : "image files", extensions : "gif,jpg,jpeg,png,bmp,ico"}  //gif|jpg|jpeg|png
		            ],
		            prevent_duplicates : true//不允许选取重复文件
		        },
		        //PreInit events, bound before the internal events
		        preinit : {
		            Init: function(up, info) {
		            },
		            UploadFile: function(up, file) {
		                up.setOption('multipart_params', {file_id:customOption.file_id,file_type:file.type,original_file_name:file.name});
		            }
		        },
		        // Post init events, bound after the internal events
		        init : {
					/**
					 * 当Init事件发生后触发
					 * 监听函数参数：(uploader)
					 * uploader为当前的plupload实例对象
					 */
					PostInit: function(up) {//当Init事件发生后触发
						var uploadfiles_id=up.getOption("uploadfiles");
						if($("#"+uploadfiles_id).length>0){
							$('#'+uploadfiles_id).bind('click', function(){up.start();});
						}
					},
					Browse: function(up) {
		                // Fires when browse_button is clicked and browse dialog shows.
						console.log('Browse');
		            },
					/**
					 * 当使用Plupload实例的setOption()方法改变当前配置参数后触发
					 * 监听函数参数：(uploader,option_name,new_value,old_value)
					 * uploader为当前的plupload实例对象，option_name为发生改变的参数名称，new_value为改变后的值，old_value为改变前的值
					 */
					OptionChanged:function(uploader,option_name,new_value,old_value){
						// Called when one of the configuration options is changed
					},
					/**
					 * 当调用plupload实例的refresh()方法后会触发该事件，暂时不清楚还有什么其他动作会触发该事件，但据我测试，把文件添加到上传队列后也会触发该事件。
					 * 监听函数参数：(uploader)
					 * uploader为当前的plupload实例对象
					 */
					Refresh: function(uploader) {
						console.log('Refresh');
						// Called when the position or dimensions of the picker change
					},
					/**
					 * 当使用Plupload实例的setOption()方法改变当前配置参数后触发
					 * 监听函数参数：(uploader,option_name,new_value,old_value)
					 * uploader为当前的plupload实例对象，option_name为发生改变的参数名称，new_value为改变后的值，old_value为改变前的值
					 */
					StateChanged: function(uploader) {
						
					},
					/**
					 * 当上传队列中某一个文件开始上传后触发
					 * 监听函数参数：(uploader,file)
					 * uploader为当前的plupload实例对象，file为触发此事件的文件对象
					 */
					UploadFile:function(up,file){
						
					},
					/**
					 * 当队列中的某一个文件正要开始上传前触发
					 * 监听函数参数：(uploader,file)
					 * uploader为当前的plupload实例对象，file为触发此事件的文件对象
					 */
					BeforeUpload:function(up,file){
						// Called right before the upload for a given file starts, can be used to cancel it if required
						
					},
					/**
					 * 当上传队列发生变化后触发，即上传队列新增了文件或移除了文件。QueueChanged事件会比FilesAdded或FilesRemoved事件先触发
					 * 监听函数参数：(uploader)
					 * uploader为当前的plupload实例对象
					 */
					QueueChanged:function(up){
						// Called when queue is changed by adding or removing files
					},
		 			/**
					  * 会在文件上传过程中不断触发，可以用此事件来显示上传进度
					  * 监听函数参数：(uploader,file)
					  * uploader为当前的plupload实例对象，file为触发此事件的文件对象
		 			*/
		            UploadProgress: function(up, file) {
		                // Called while file is being uploaded
		            },
					/**
					 * 暂不清楚该事件的意义，但根据测试得出，该事件会在每一个文件被添加到上传队列前触发
					 * 监听函数参数：(uploader,file)
					 * uploader为当前的plupload实例对象，file为触发此事件的文件对象
					 * */
					FileFiltered: function(up, file) {
						// Called when file successfully files all the filters
					},
		 
		 			/**
					  * 当文件从上传队列移除后触发
					  * 监听函数参数：(uploader,files)
					  * uploader为当前的plupload实例对象，files为一个数组，里面的元素为本次事件所移除的文件对象
		 			*/
		            FilesRemoved: function(up, files) {
		                // Called when files are removed from queue
		                /*plupload.each(files, function(file) {
		                    log('  File:', file);
		                });*/
		            },
					/**
					  * 当使用文件小片上传功能时，每一个小片上传完成后触发
					  * 监听函数参数：(uploader,file,responseObject)
					  * uploader为当前的plupload实例对象，file为触发此事件的文件对象，responseObject为服务器返回的信息对象，它有以下5个属性：
					  * offset：该文件小片在整体文件中的偏移量
					  * response：服务器返回的文本
					  * responseHeaders：服务器返回的头信息
					  * status：服务器返回的http状态码，比如200
					  * total：该文件(指的是被切割成了许多文件小片的那个文件)的总大小，单位为字节
					*/
		            ChunkUploaded: function(up, file, info) {
		                // Called when file chunk has finished uploading
		            },
					/**
					 * 当文件添加到上传队列后触发
					 * 监听函数参数：(uploader,files)
					 * uploader为当前的plupload实例对象，files为一个数组，里面的元素为本次添加到上传队列里的文件对象
					 * */
					FilesAdded: function(up, files) {
						console.log('FilesAdded');
						// Called when files are added to queue
						if(!customOption.multi_selection){//单选
							var allAddedFiels=up.files;
							if(allAddedFiels.length>1){
								up.splice(0, 1);//移除上次加入队列的文件
							}
						}
						if(customOption.FilesAddedCallBack){
							customOption.FilesAddedCallBack(up, files);
						}
						//$.messager.alert("提示", JSON.stringify(files));
		            },
					/**
					 * 当队列中的某一个文件上传完成后触发
					 * 监听函数参数：(uploader,file,responseObject)
					 * uploader为当前的plupload实例对象，file为触发此事件的文件对象，responseObject为服务器返回的信息对象，它有以下3个属性：
					 * response：服务器返回的文本
					 * responseHeaders：服务器返回的头信息
					 * status：服务器返回的http状态码，比如200
					 * */
					FileUploaded: function(up, file, info){//单个文件上传完成后
						console.log(info);
						// Called when file has finished uploading
						var result=JSON.parse(info.response);
						if(result.success||result.status==200){
							up.removeFile(file.id);//从上传队列中移除
						}else{
							file.status=plupload.FAILED;
							$.messager.alert("提示", "文件"+file.name+"上传失败："+result.message);
						}
						customOption.FileUploadedCallBack(up,file,result.data);
					},
					/**
					 * 当上传队列中所有文件都上传完成后触发
					 * 监听函数参数：(uploader,files)
					 * uploader为当前的plupload实例对象，files为一个数组，里面的元素为本次已完成上传的所有文件对象
					 * */
					UploadComplete: function(up, files){//文件全部上传完成
						console.log(up);
						console.log(files);
						// Called when all files are either uploaded or failed
						//文件的状态，可能为以下几个值之一：plupload.QUEUED, plupload.UPLOADING, plupload.FAILED, plupload.DONE
						var success=true;
						for(var i=0;i<files.length;i++){
							if(files[i].status==plupload.FAILED){
								success=false;
								break;
							}
						}
						if(success){
							info("上传成功！");
						}
						customOption.UploadCompleteCallBack(up, files);
					},
					/**
					 * 当发生错误时触发
					 * 监听函数参数：(uploader,errObject)
					 * uploader为当前的plupload实例对象，errObject为错误对象，它至少包含以下3个属性(因为不同类型的错误，属性可能会不同)：
					 * code：错误代码，具体请参考plupload上定义的表示错误代码的常量属性
					 * file：与该错误相关的文件对象
					 * message：错误信息
					 * */
		            Error: function(up, err) {
		             	$.messager.alert("提示", "错误:"+err.message);
		            },
					/**
					 * 当调用destroy方法时触发
					 * 监听函数参数：(uploader)
					 * uploader为当前的plupload实例对象
					 * */
					Destroy: function(up) {
						// Called when uploader is destroyed
						
					}
				}
		};
		this.uploaderOption = $.extend(true,{},defaultOption,customOption);
		this.uploader = new plupload.Uploader(this.uploaderOption);
		this.uploader.init();
		this.start=function(){this.uploader.start();};
		this.destroy=function(){this.uploader.destroy();};
		this.previewImage=function(file, callback){//file为plupload事件监听函数参数中的file对象,callback为预览图片准备完成的回调函数
		    if (!file || !/image\//.test(file.type)) return; //确保文件是图片
		    if (file.type == 'image/gif') {//gif使用FileReader进行预览,因为mOxie.Image只支持jpg和png
		        var fr = new mOxie.FileReader();
		        fr.onload = function () {
		            callback(fr.result);
		            fr.destroy();
		            fr = null;
		        }
		        fr.readAsDataURL(file.getSource());
		    } else {
		        var preloader = new mOxie.Image();
		        preloader.onload = function () {
		            //preloader.downsize(550, 400);//先压缩一下要预览的图片,宽300，高300
		            var imgsrc = preloader.type == 'image/jpeg' ? preloader.getAsDataURL('image/jpeg', 80) : preloader.getAsDataURL(); //得到图片src,实质为一个base64编码的数据
		            callback && callback(imgsrc); //callback传入的参数为预览图片的url
		            preloader.destroy();
		            preloader = null;
		        };
		        preloader.load(file.getSource());
		    }
		}
	}
